package com.ytjj.quartz.service;

import com.github.pagehelper.PageHelper;
import com.ytjj.quartz.dao.MessageDao;
import com.ytjj.quartz.model.MessageResponse;
import com.ytjj.quartz.model.dto.MessageTelResponse;
import com.ytjj.quartz.utils.SMProxyTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 *
 * 
 * @Version: 1.0
 */
@Service
@Slf4j
public class MessageService {

	@Resource
	private MessageDao messageDao;
	// 开启线程池
	static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2,
			60L, TimeUnit.SECONDS,
			new SynchronousQueue<Runnable>());

	/**
	 * 单笔发送
	 */
	public void sendMessageBySimple() {
		Integer pageNum = 1;
		Integer pageSize = 5;
		PageHelper.startPage(pageNum, pageSize);
		List<MessageResponse> msgList = messageDao.getSendMessageList(pageNum, pageSize);
		for (MessageResponse message : msgList) {
			messageDao.updateSendingStatus(message.getId());//发送中

			synSendMessageByMessageNo(message);//发送消息

			messageDao.updateSendStatus(message.getId());//发送完成
		}
	}

	public synchronized void synSendMessageByMessageNo(MessageResponse message) {
		Integer pageNum = 1;
		Integer pageSize = 1000;
		while(true) {
			PageHelper.startPage(pageNum, pageSize);
			List<MessageTelResponse> telList = messageDao.getMessageTelList(message.getId().toString());
			if (CollectionUtils.isEmpty(telList)) {
				return;
			}
			List<Map<String, Integer>> list = setMessageBySimple(telList, message.getContent());
			Map<String, Integer> map = list.get(0);
			Integer successNum = map.get("SUCCESS");
			Integer failNum = map.get("FAIL");
			messageDao.updateSendNum(message.getId(), successNum, failNum);
			pageNum++;
		}
	}

	public void sendMessage() {
		boolean key = true;
		Integer pageNum = 1;
		Integer pageSize = 1000;
		while (key) {
			PageHelper.startPage(pageNum, pageSize);
			List<MessageResponse> msgList = messageDao.getSendMessageList(pageNum, pageSize);
			log.info("===msgList.size()==={}", msgList.size());
			if(msgList.size() == pageSize) {
				pageNum++;
			} else {
				key = false;
			}
			threadPoolExecutor.execute(new TransferUserHandler(msgList));
		}
	}
	// 多线程实现
	class TransferUserHandler implements Runnable {
		private List<MessageResponse> msgList;

		public TransferUserHandler(List<MessageResponse> messageList) {
			this.msgList = messageList;
		}

		@Override
		public void run() {
			// 先将短信状态修改为已执行，再跑数据
			log.info("===msgList==={}", msgList.size());
			if(!CollectionUtils.isEmpty(msgList)) {
				for(MessageResponse res : msgList) {
					Date sendTime = res.getSendTime();
					// 判断当前时间与需要执行的发送时间是否一致
					messageDao.updateSendStatus(res.getId());
				}
			}
			if(!CollectionUtils.isEmpty(msgList)) {
				for(MessageResponse res : msgList) {
					// 判断当前时间与需要执行的发送时间是否一致
					// 根据短信编号获取其下短信手机号列表
					List<MessageTelResponse> telList = messageDao.getMessageTelList(res.getId().toString());
					List<Map<String, Integer>> list = setMessage(telList, res.getContent());
					Map<String, Integer> map = list.get(0);
					Integer successNum = map.get("SUCCESS");
					Integer failNum = map.get("FAIL");
					messageDao.updateSendNum(res.getId(), successNum, failNum);
				}
			}
		}
	}

	/**
	 * 时间 年月日时分 比较
	 * @param sendTime
	 * @return
	 */
	public boolean compareTime(Date sendTime) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		String targetTime = sdf.format(sendTime);
		String nowTime = sdf.format(new Date());
		return targetTime.equals(nowTime);
	}


	/**
	 * 发送短信-属性设置
	 * @param telList
	 */
	public List<Map<String, Integer>> setMessageBySimple(List<MessageTelResponse> telList, String content) {
		// 发送短信成功/失败次数
		AtomicInteger successNum = new AtomicInteger();
		AtomicInteger failNum = new AtomicInteger();
		if(!CollectionUtils.isEmpty(telList)) {
			for(MessageTelResponse mess : telList) {
				try {
					String[] phones = {mess.getTel()};
					boolean resultCMPP = SMProxyTools.sendMsg(phones, content);
					log.debug("===resultCMPP==={}", resultCMPP);
					if(resultCMPP) {
						successNum.getAndIncrement();
					} else {
						failNum.getAndIncrement();
					}
					messageDao.updateStatus(mess.getTel(), resultCMPP ? 3 : 4);
				} catch (Exception e) {
					messageDao.updateStatus(mess.getTel(), 4);
					e.printStackTrace();
				}
			}

		}
		List<Map<String, Integer>> list = new ArrayList<>();
		Map<String, Integer> map = new HashMap<>();
		map.put("SUCCESS", successNum.get());
		map.put("FAIL", failNum.get());
		list.add(map);
		return list;
	}

	/**
	 * 发送短信-属性设置
	 * @param telList
	 */
	public List<Map<String, Integer>> setMessage(List<MessageTelResponse> telList, String content) {
		// 发送短信成功/失败次数
		AtomicInteger successNum = new AtomicInteger();
		AtomicInteger failNum = new AtomicInteger();
		int mol = telList.size() % 50;
		int forNum = telList.size() / 50;
		if (mol > 0) {
			forNum = forNum + 1;
		}
		for (int i = 0; i < forNum; i++) {
			List<MessageTelResponse> phoneStrs = new ArrayList<>();
			if (i * 50 + 50 > telList.size()) {
				phoneStrs = telList.subList(i * 50, telList.size());
			}else {
				phoneStrs = telList.subList(i * 50, i * 50 + 50);
			}
			List<String> phoneArray = phoneStrs.stream().map(MessageTelResponse::getTel).collect(Collectors.toList());
			String[] phones = null;
			try {
				phones = phoneArray.toArray(new String[phoneStrs.size()]);
				boolean resultCMPP = SMProxyTools.sendMsg(phones, content);
				log.info("===resultCMPP==={}", resultCMPP);
				if(resultCMPP) {
					successNum.addAndGet(phones.length);
				} else {
					failNum.addAndGet(phones.length);
				}
				messageDao.updateStatusByTels(Arrays.asList(phones), 3);
			} catch (Exception e) {
				messageDao.updateStatusByTels(Arrays.asList(phones), 4);
				e.printStackTrace();
			}

		}
		List<Map<String, Integer>> list = new ArrayList<>();
		Map<String, Integer> map = new HashMap<>();
		map.put("SUCCESS", successNum.get());
		map.put("FAIL", failNum.get());
		list.add(map);
		return list;
	}

	public static void main(String[] args) {


//		List<MessageTelResponse> telList = new ArrayList<>();
//		Random random = new Random();
//		for (int i = 0; i < 50000; i++) {
//			MessageTelResponse mt1 = new MessageTelResponse();
//			mt1.setId(1);
//			mt1.setTel("15797" + random.nextInt(100000));
//			mt1.setOperatorType(1);
//			telList.add(mt1);
//		}
//		setMessage(telList, "【XXXX优品】尊敬的严选会员，平台正招募商品测评师，现登陆可免费领取一份商品测评，详情点:xxx 退订回T");
	}
}
